/*
* baseTable表格公共组件
*/
import React, { Component, forwardRef } from 'react'
import { Table, Button } from 'antd'
import { connect } from 'react-redux'
import { withRouter } from 'react-router'
import PropTypes from 'prop-types'
import _ from 'lodash'
import _fetch from '@/Utils/Fetch'
import {
  pub_rowSelectionToStore,
  pub_getAllTableData,
  pub_isLoading,
  pub_currntPage,
  pub_clearSelectedData,
  pub_setSelectedStatus
} from '@/Redux/ActionTypes/public/BaseTable/publicActionCreator'
import Previewer from '../../preViewer'
import { injectUnmount, planeTree } from '@/Utils'
import './index.css'

// 把页面需要用到的数据和方法映射到props里面
const mapStateToProps = (state) => {
  return {
    pub_allTableData: state.baseTable.pub_allTableData, // 获取表格所有数据
    pub_isLoading: state.baseTable.pub_isLoading, // 是否拿到表格数据的标识
    fixedConf: state.baseTable.fixedConf, // 当前是第几页
    allSearchCondition: state.baseTable.allSearchCondition, // 所有搜索条件
    pub_rowSelection: state.baseTable.pub_rowSelection,
    pub_selectedStatus: state.baseTable.selectedStatus,
  }
}

const mapDispatchToProps = (dispatch) => ({
  getRowSelection(...rest) {
    return dispatch(pub_rowSelectionToStore(...rest)); // 把选中的当行数据发送到store
  },
  getAllTableData(...rest) {
    return dispatch(pub_getAllTableData(...rest)); // 把获取到的表格所有数据发送到store
  },
  pub_changeisLoading(...rest) {
    return dispatch(pub_isLoading(...rest)); // 把标志是否获取表格数据的isLoading标识修改
  },
  pub_changeCurrentPage(...rest) {
    return dispatch(pub_currntPage(...rest)); // 把改变后的页数发送到store
  },
  pub_clearSelectedData(...rest) {
    return dispatch(pub_clearSelectedData(...rest)); // 清除选中数据
  },
  pub_setSelectedStatus(...rest) {
    return dispatch(pub_setSelectedStatus(...rest));
  },
})

class BaseTable extends Component {
  constructor(props) {
    super(props);
    const { location: { pathname }, markName } = this.props;// 写在这里的目的是为了将来一个页面可能会有多个表单。 将来在这里改一下标识即pathname就可以
    this.markId = markName ? markName : pathname; // 如果是模态框用到了公共表格组件，就传name
  }

  state = {
    // 设置被选中的文件状态
    selectStatus: null
  }

  componentDidUpdate(preProps, preState) {
    if (preProps.location.pathname !== this.props.location.pathname
      && preState.selectStatus !== null) {
      this.setState({ selectStatus: null })
    }

    // 如果状态为请求刷新后的，则清空所选数据
    if (this.props.pub_selectedStatus === -2) {
      const { pub_setSelectedStatus, getRowSelection } = this.props;
      pub_setSelectedStatus(null);
      this.setState({ selectStatus: null });
      getRowSelection([], this.markId) // 把选中的当行数据发送给store
    }
  }

  static defaultProps = {
    withPreview: true
  }
  // 设置表格头
  returnColumns = () => {
    const { tableConfig, withPreview, operationButton } = this.props;
    let columns = [];
    if (withPreview) {
      columns.push({
        title: "预览",
        width: 50,
        dataIndex: 'preview',
        key: 'preview',
        fixed: 'left',
        render: (text, record) => <Previewer    // 给预览图添加点击事件和鼠标
          click={
            this.props.stylePointer ?
              () => {
                this.clickEvent(record)
              }
              : null
          }
          style={this.props.stylePointer && { cursor: 'pointer' }}
          url={record.url} isThumbnail={true} />
      });
    }

    tableConfig.forEach((value, index) => {
      // 取出属性名
      let keys = Object.keys(value);
      let title = keys[0];
      let width = keys.includes("width") ? "width" : 0;
      // 根据title设置渲染规则
      let change = null;
      switch (title) {
        // case 'departmentId':
        //   change = department;
        //   break;
        default:
          break;
      }

      let columnsConfig = {
        title: value[title],
        dataIndex: title,
        key: title,
        width: width ? value[width] : 100,
        ellipsis: true,
        render: value.render,
      };
      // 如果有需要特殊渲染的则加上渲染规则
      if (columnsConfig.render !== undefined) {
        //如果有渲染函数,就什么也不干
      } else if (change) {
        columnsConfig.render = text => change[text] || '无'
      } else if (columnsConfig.key === 'grade') {
        columnsConfig.render = text => {
          switch (text) {
            case 0:
              return '学前班'
            case 1:
              return '一年级'
            case 2:
              return '二年级'
            case 3:
              return '三年级'
            case 4:
              return '四年级'
            case 5:
              return '五年级'
            case 6:
              return '六年级'
            case 7:
              return '初一'
            case 8:
              return '初二'
            case 9:
              return '初三'
            case 10:
              return '高一'
            case 11:
              return '高二'
            case 12:
              return '高三'
            default:
              break;
          }
        }
      } else {
        columnsConfig.render = text => {
          if (text === null || text === undefined) return '无';
          return text;
        }
      }
      columns.push(columnsConfig)
    })
    // 自定义操作按钮
    const { noOperationButton } = this.props;
    if (!noOperationButton) {
      columns.push({
        title: '操作',
        key: 'viewdetails',
        fixed: 'right',
        width: 100,
        render: (text, record) => {
          return operationButton ? operationButton(record) : <Button onClick={() => { this.clickEvent(record) }}>查看</Button>
        }   // 多层判断决定是否自定义按钮
      })
    }
    return columns;
  }



  // 查看详情事件执行函数
  clickEvent = (record) => {
  }

  // 分页改变时可以调用
  // 返回获取到的表格数据，搜索时可用
  returnAllTableData = async (page, pageSize) => {
    const { getAllTableData, changeTableData, pub_changeisLoading, allSearchCondition } = this.props;
    const searchData = _.cloneDeep(allSearchCondition[this.markId]);
    searchData.page = page; // 增加分页器条件,从state里面拿current，因为分页器onChange会改变这个值
    searchData.size = pageSize;
    const ajaxConfig = searchData.ajaxConfig;
    delete searchData.ajaxConfig; // 记得删掉
    pub_changeisLoading(true, this.markId); // 先置为true
    let result = await this.searchFunc(ajaxConfig, searchData); // 如果是搜索的话，就传搜索条件data
    let tableData = {}
    if (result && result.data.data) {
      tableData = changeTableData(result.data.data) // 调用父组件传来的changeTableData，修改获得的表格的数据成符和格式的数据
      let Data = _.cloneDeep(tableData); // 深拷贝一份数据
      Data.data.forEach((item) => { // 让每一个表格数据都获得key
        item.key = item.id ? item.id : item.stuId;
      })
      pub_changeisLoading(false, this.markId); // 获取到数据就置为false
      getAllTableData(Data, this.markId); // 把表格数据发送到store
    }
  }

  searchFunc = (ajaxConfig, data) => { // 请求后台表格数据，发送请求时应该先请求第一页数据
    const { ajaxType, url, ContentType = 'application/json' } = ajaxConfig;
    let option = {
      type: ajaxType,
      url,
      data,
      headers: {
        'Content-Type': ContentType // 默认是'application/json'
      }
    }
    return _fetch(option)
  }

  returnRowSelection = (record) => {  // 返回表格的行配置
    const { getRowSelection, pub_rowSelection, location, notRowSelection } = this.props;
    if (notRowSelection) return null;    // 如果配置有需要不用多选框则返回null
    const selectedData = pub_rowSelection[this.markId] || [];
    if (record) {   // 如果触发行触
      if (_.find(selectedData, record)) {    //原先数据如果存在 取消选中
        _.remove(selectedData, record)    // 删掉
        getRowSelection(selectedData, this.markId)    // 更新store
      } else {
        getRowSelection([record, ...selectedData], this.markId) // 把选中的当行数据发送给store
      }
    }

    const onSelect = (record, selected, selectedRows, event) => { //判断是选中还是取消，选中直接添加，取消就从store里面删掉，下面同理
      if (selected) {
        getRowSelection([record, ...selectedData], this.markId)
      } else {
        let newSeletedData = selectedData.filter(item => {
          if (item.id) {
            return item.id !== record.id;
          } else {
            return item.stuId !== record.stuId;
          }
        })
        getRowSelection(newSeletedData, this.markId)
      }
    }

    const onSelectAll = (selected, selectedRows, changeRows) => { // 全选对数据的处理
      if (selected) {
        getRowSelection([...changeRows, ...selectedData], this.markId)
      } else {
        let newSeletedData = [...selectedData]; //拷贝一份
        changeRows.forEach(item => {
          _.remove(newSeletedData, item); //删除取消全选的所有项
        })
        getRowSelection(newSeletedData, this.markId);
      }
    }

    const rowSelection = {
      type: 'checkbox',
      onSelect,
      onSelectAll,
      selectedRowKeys: pub_rowSelection[this.markId] ? pub_rowSelection[this.markId].map(item => (item.id ? item.id : item.stuId)) : [],
    }

    if (location.pathname.includes('workStation')) {
      const { selectStatus } = this.state;
      const { pub_setSelectedStatus } = this.props;

      // 配置只有status等于当前选中的项的status才可以被选中
      rowSelection.getCheckboxProps = (record) => (
        selectStatus === null ? {
          disabled: false
        }
          : {
            disabled: record.status !== selectStatus,    // 配置无法勾选的列
          }
      )
      // 只有当前有选中项才可以全选
      rowSelection.hideSelectAll = selectStatus === null ? true : false;
      // 设置当前选中项的status到state里面
      // 把当前选中的项的状态存进redux
      rowSelection.onSelect = (record, selected, selectedRows) => {
        pub_setSelectedStatus(record.status);
        if (selected) {
          if (record.status !== this.state.selectStatus) {
            this.setState({ selectStatus: record.status });
            pub_setSelectedStatus(record.status);
          }
          getRowSelection([record, ...selectedData], this.markId)
        } else {
          if (selectedRows.length === 0) {
            this.setState({ selectStatus: null });
            pub_setSelectedStatus(null);
          }
          let newSeletedData = selectedData.filter(item => {
            return item.id !== record.id;
          })
          getRowSelection(newSeletedData, this.markId)
        }
      }
      // 当取消全选时清空state里的selectStatus
      rowSelection.onSelectAll = (selected, selectedRows, changeRows) => {
        if (!selected) {
          let newSeletedData = [...selectedData]; //拷贝一份
          changeRows.forEach(item => {
            _.remove(newSeletedData, item); //删除取消全选的所有项
          })
          getRowSelection(newSeletedData, this.markId);
          this.setState({ selectStatus: null });
          pub_setSelectedStatus(null);
        }
      }
    }
    return rowSelection;
  }
  isLoading = () => { // 返回loading，首次加载和搜索时,后台数据还未返回就会先出现loading标志
    return this.props.pub_isLoading[this.markId];
  }

  // 生成分页显示器配置
  returnPagination = () => {
    const { pub_allTableData, noShowQuickJumper } = this.props;
    let temp = pub_allTableData[this.markId];
    if (temp && temp.total !== undefined && temp.current !== undefined) { // 确保temp存在并且有total字段和current字段
      const { total, pageSize, current } = temp; // 从props里面拿分页器设置，根据后台返回数据
      // 改变 页数 或者 pageSize切换器大小 时触发
      let onChange = (page, pageSize) => {
        // console.log(page)
        return this.returnAllTableData(page, pageSize)
      };
      // 显示目前位置
      let showTotal = () => {
        let start = (current - 1) * pageSize + 1,
          tempEnd = (current * pageSize),
          end = tempEnd > total ? total : tempEnd;
        return `显示 第 ${end === 1 ? '1 ' : `${start} - ${end}`} 条 ， 共  ${total} 条`
      }
      // 分页显示器配置
      let pagination = {
        position: ["bottomCenter"], // 分页器位置统一设置在bottomCenter
        total, // 数据总数
        current, // 当前页数，后台会默认第一页
        pageSize, // 每页条数
        showSizeChanger: true, // 是否展示 pageSize 切换器
        onChange: onChange, // 页码改变的回调，参数是改变后的页码及每页条数
        showTotal: showTotal, // 用于显示数据总量和当前数据顺序
        showQuickJumper: noShowQuickJumper === false ? noShowQuickJumper : true, // 直接跳转到某一页
      }
      return pagination
    }
    return {}
  }

  returnData = () => { // 返回对应的tableData
    const { pub_isLoading, pub_allTableData, withPreview } = this.props;
    let temp = pub_allTableData[this.markId];
    let data = [];
    if (temp !== undefined && !pub_isLoading[this.markId]) {
      temp.data.forEach((value, index) => {
        if (withPreview) {
          const { type, fileToken, fileType, thumbnailFileToken, thumbnailFileType } = value;
          const fileData = { fileToken: fileToken || thumbnailFileToken, fileType: fileType || thumbnailFileType }
          value.preview = { type, fileData }
        }
        data.push(value);
      })
    }
    return data
  }

  render() {
    const columns = this.returnColumns(),
      dataSource = this.returnData(),
      loading = this.isLoading(),
      pagination = this.returnPagination(),
      rowSelection = this.props.rowSelection || this.returnRowSelection(),
      onRow = this.props.onRow || this.returnRowSelection;

    return (
      <Table
        bordered
        scroll={{ x: 1000, y: Number(sessionStorage.getItem('tableHeight')) }}
        className="base-table"
        columns={columns} // 表格列的配置描述，更多配置可以查看antd的表格columns配置
        dataSource={dataSource} // 数据数组
        loading={loading}
        pagination={pagination} // 分页的配置
        rowSelection={rowSelection}   // 多选框配置
        onRow={   // 行触事件
          this.props.onRowEvent ?
            (record) => ({
              onClick: () => {
                onRow(record);
              },
            }) : null
        }
      />
    )
  }
}
// 对传入的属性进行类型检查
BaseTable.propTypes = {
  changeSearchLimit: PropTypes.func, // 增加修改限制
  changeTableData: PropTypes.func, // 修改表格数据
}

@connect(mapStateToProps, mapDispatchToProps) // 装饰器
@withRouter
@injectUnmount
class TableRef extends Component {
  render() {
    return (<BaseTable {...this.props} ref={this.props.myForwardedRef} />) // 转发ref，不然拿到的是connect高阶组件的ref
  }
}

export default forwardRef((props, ref) =>
  <TableRef {...props} myForwardedRef={ref} />
)